﻿using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using System.Web;
using Newtonsoft.Json.Linq;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Modes;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.OpenSsl;
using Org.BouncyCastle.Security;
namespace XQ.Framework.WeChatPay
{
    public class WechatPayV3NotifyHandler
    {
        // 微信支付APIv3密钥（商户平台配置）
        public string API_V3_KEY { get; set; }
        public string signature { get; set; }
        public string timestamp { get; set; }
        public string nonce { get; set; }
        public string serialNo { get; set; }

        public string requestBody { get; set; }
        public PayResultModel ProcessNotify()
        {
            try
            {

                if (string.IsNullOrEmpty(signature))
                    throw new Exception("缺少Wechatpay-Signature头信息");

                // 3. 使用微信支付公钥验证签名
                if (!VerifySignatureWithPublicKey(requestBody, signature, timestamp, nonce, serialNo))
                {
                    throw new Exception("签名验证失败");
                }

                // 4. 解析并解密通知数据
                JObject notifyData = JObject.Parse(requestBody);
                JObject resource = (JObject)notifyData["resource"];

                string cipherText = resource["ciphertext"].ToString();
                string associatedData = resource["associated_data"]?.ToString();
                string nonceStr = resource["nonce"].ToString();

                // 5. 解密业务数据
                string plainText = AesGcmDecrypt(cipherText, API_V3_KEY, nonceStr, associatedData);

                // 6. 处理业务逻辑（示例）
                JObject result = JObject.Parse(plainText);
                string outTradeNo = result["out_trade_no"].ToString();
                string transactionId = result["transaction_id"].ToString();
                string openid = result["payer"]["sub_openid"].ToString();

                // TODO: 更新订单状态、记录支付信息等业务处理
                PayResultModel payResultModel = new PayResultModel();
                payResultModel.outTradeNo = outTradeNo;
                payResultModel.transactionId = transactionId;
                payResultModel.openid = openid;
                payResultModel.allData = result;
                payResultModel.code = "SUCCESS";
                payResultModel.message = "成功";

                // 7. 返回成功响应
                return payResultModel;
            }
            catch (Exception ex)
            {
                PayResultModel payResultModel = new PayResultModel();
                payResultModel.code = "FAIL";
                payResultModel.message = ex.Message.Replace("\"", "\\\"");
                // 返回错误响应
                return payResultModel;
            }
        }

        /// <summary>
        /// 使用微信支付平台公钥验证签名
        /// </summary>
        private bool VerifySignatureWithPublicKey(
            string body,
            string signature,
            string timestamp,
            string nonce,
            string serialNo)
        {
            // 1. 构造签名字符串（微信V3规范）
            string signContent = $"{timestamp}\n{nonce}\n{body}\n";

            // 2. 根据证书序列号获取微信支付平台公钥
            string publicKeyPem = GetWechatPublicKey(serialNo);
            if (string.IsNullOrEmpty(publicKeyPem))
                throw new Exception($"未找到序列号[{serialNo}]的微信支付平台公钥");

            // 3. 使用BouncyCastle解析公钥
            AsymmetricKeyParameter publicKey = ParsePublicKey(publicKeyPem);
            if (!(publicKey is RsaKeyParameters rsaKey))
                throw new Exception("无效的RSA公钥");

            // 4. 转换为.NET的RSAParameters
            RSAParameters rsaParams = DotNetUtilities.ToRSAParameters(rsaKey);

            // 5. 验证签名
            using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
            {
                rsa.ImportParameters(rsaParams);

                byte[] signBytes = Convert.FromBase64String(signature);
                byte[] dataBytes = Encoding.UTF8.GetBytes(signContent);

                return rsa.VerifyData(
                    dataBytes,
                    CryptoConfig.MapNameToOID("SHA256"),
                    signBytes
                );
            }
        }

        /// <summary>
        /// 解析PEM格式的公钥
        /// </summary>
        private AsymmetricKeyParameter ParsePublicKey(string publicKeyPem)
        {
            using (StringReader reader = new StringReader(publicKeyPem))
            {
                PemReader pemReader = new PemReader(reader);
                object keyObject = pemReader.ReadObject();

                if (keyObject is RsaKeyParameters rsaKey)
                    return rsaKey;

                if (keyObject is AsymmetricCipherKeyPair keyPair)
                    return keyPair.Public;

                throw new Exception("无法解析PEM公钥");
            }
        }

        /// <summary>
        /// 获取微信支付平台公钥（PEM格式）
        /// </summary>
        private string GetWechatPublicKey(string serialNo)
        {
            // TODO: 实现从存储获取公钥的逻辑
            // 这里应该是从数据库/文件/缓存中获取对应序列号的公钥
            // 示例返回一个硬编码的公钥（实际使用时需要替换）
            return @"-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqQTf0jL9w3OvaV6z7moC
6gZPtMy+ZPaUMwxLpnmTImJCVzD4gO/MzRLcaXJ+VeDxAQK+2weIEo1oTssIaUM/
hDLMC/I5zIymPrgt152QM8GP6PvJQcUSsGp4NQzC3WoWcUQo6x2xq+cXjGo78rEL
6LAS4Y7XYBk6GeJxN4JIg0GUOjfebunVHFcm72M6kqZBtO2OpX2CWNqLsMvKBvw8
EIITWZFHnkH/If4ys5a42JLZcQ/QSGb0zN4RtEvYqiPiaimGT6Myca1tYUFX+TDp
GMbfGDP3g4FLz+h+FKJ0MQIDevWAFiKAZian/Z5wWqB1Me7SeZ9BMoRDxaKMGu/Y
kQIDAQAB
-----END PUBLIC KEY-----";
        }

        /// <summary>
        /// AES-GCM解密（使用BouncyCastle）
        /// </summary>
        private string AesGcmDecrypt(string ciphertext, string key, string nonce, string associatedData)
        {
            try
            {
                byte[] keyBytes = Encoding.UTF8.GetBytes(key);
                byte[] nonceBytes = Encoding.UTF8.GetBytes(nonce);
                byte[] associatedBytes = string.IsNullOrEmpty(associatedData)
                    ? new byte[0]
                    : Encoding.UTF8.GetBytes(associatedData);
                byte[] cipherBytes = Convert.FromBase64String(ciphertext);

                // 微信V3加密格式：ciphertext = encrypted_data + tag
                int tagLength = 16;
                byte[] encryptedData = new byte[cipherBytes.Length - tagLength];
                byte[] tag = new byte[tagLength];
                Buffer.BlockCopy(cipherBytes, 0, encryptedData, 0, encryptedData.Length);
                Buffer.BlockCopy(cipherBytes, encryptedData.Length, tag, 0, tagLength);

                // 使用BouncyCastle进行AES-GCM解密
                GcmBlockCipher cipher = new GcmBlockCipher(new AesEngine());
                AeadParameters parameters = new AeadParameters(
                    new KeyParameter(keyBytes),
                    128,
                    nonceBytes,
                    associatedBytes
                );

                cipher.Init(false, parameters);

                // 合并加密数据和认证标签
                byte[] cipherTextWithTag = new byte[encryptedData.Length + tagLength];
                Buffer.BlockCopy(encryptedData, 0, cipherTextWithTag, 0, encryptedData.Length);
                Buffer.BlockCopy(tag, 0, cipherTextWithTag, encryptedData.Length, tagLength);

                byte[] plainBytes = new byte[cipher.GetOutputSize(cipherTextWithTag.Length)];
                int len = cipher.ProcessBytes(cipherTextWithTag, 0, cipherTextWithTag.Length, plainBytes, 0);
                len += cipher.DoFinal(plainBytes, len);

                return Encoding.UTF8.GetString(plainBytes, 0, len);
            }
            catch (Exception ex)
            {
                throw new Exception($"AES-GCM解密失败: {ex.Message}");
            }
        }

    }
}
